package com.zhao.dota.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhao.dota.bo.AuthenticateUser;
import com.zhao.dota.mapper.RoundMapper;
import com.zhao.dota.model.Quotation;
import com.zhao.dota.model.Round;
import com.zhao.dota.security.SecurityUtil;
import com.zhao.dota.service.QuotationService;
import com.zhao.dota.service.RoundService;
import com.zhao.dota.service.UserHeroService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RoundServiceImpl extends ServiceImpl<RoundMapper, Round> implements RoundService {

    @Resource
    private QuotationService quotationService;
    @Resource
    private UserHeroService userHeroService;

    @Override
    public List<Round> leagueRound(Integer leagueId) {
        LambdaQueryWrapper<Round> query = Wrappers.lambdaQuery(Round.class)
                .eq(Round::getLeagueId, leagueId)
                .eq(Round::getState, Round.State.FINISHED);
        return list(query);
    }

    @Override
    public Round quoting(Integer leagueId) {
        LambdaQueryWrapper<Round> query = Wrappers.lambdaQuery(Round.class)
                .eq(Round::getLeagueId, leagueId)
                .ne(Round::getState, Round.State.FINISHED);
        return getOne(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean endQuotation(Integer leagueId) {
        Round quoting = quoting(leagueId);
        if (quoting != null) {
            quoting.setEndTime(LocalDateTime.now());
            quoting.setState(Round.State.SETTLING);
            updateById(quoting);
            boolean needRoll = quotationService.calUserHeroes(quoting);
            if (needRoll) {
                quoting.setState(Round.State.ROLL);
            } else {
                quoting.setState(Round.State.FINISHED);
            }
            updateById(quoting);
            return needRoll;
        }
        return false;
    }

    @Override
    public Round start(Integer leagueId, Round.Type type) {
        Round quoting = quoting(leagueId);
        if (quoting != null) {
            return quoting;
        }
        Round round = new Round();
        round.setLeagueId(leagueId);
        round.setType(type);
        Integer num = baseMapper.getNum(leagueId);
        if (num == null) {
            num = 1;
        } else {
            num += 1;
        }
        round.setNum(num);
        round.setStartTime(LocalDateTime.now());
        round.setState(Round.State.RUNNING);
        round.setCreateUserId(SecurityUtil.getAuthenticateUser().getId());
        save(round);
        return round;
    }

    @Override
    public void endRoll(Integer roundId) {
        quotationService.systemRoll(roundId);
        LambdaQueryWrapper<Quotation> query = Wrappers.lambdaQuery(Quotation.class)
                .isNotNull(Quotation::getPoint)
                .eq(Quotation::getRoundId, roundId);
        List<Quotation> list = quotationService.list(query);
        Map<Integer, List<Quotation>> quotationMap = list.stream().collect(Collectors.groupingBy(Quotation::getHeroId));
        List<Quotation> success = new ArrayList<>();
        List<Quotation> fail = new ArrayList<>();
        for (List<Quotation> quotations : quotationMap.values()) {
            Collections.sort(quotations);
            Collections.reverse(quotations);
            Quotation first = quotations.remove(0);
            success.add(first);
            userHeroService.getHero(first);
            fail.addAll(quotations);
        }
        for (Quotation quotation : success) {
            quotation.setSucceed(true);
        }
        for (Quotation quotation : fail) {
            quotationService.refund(quotation);
            quotation.setSucceed(false);
        }
        quotationService.updateBatchById(list);
        Round round = getById(roundId);
        round.setState(Round.State.FINISHED);
        updateById(round);
    }

    @Override
    public boolean cancelRoll(Integer roundId) {
        Round round = getById(roundId);
        if (round.getState() == Round.State.ROLL) {

        }
        return false;
    }


    @Override
    @Transactional
    public Round save(Integer leagueId, Round entity) {
        AuthenticateUser authenticateUser = SecurityUtil.getAuthenticateUser();
        if (entity.getId() == null) {
            entity.setLeagueId(leagueId);
            Round notFinished = baseMapper.getNotFinished(entity.getLeagueId());
            if (notFinished != null) {
                return notFinished;
            }
            Integer num = baseMapper.getNum(entity.getLeagueId());
            if (num == null) {
                num = 1;
            }
            entity.setNum(num);
            entity.setStartTime(LocalDateTime.now());
            entity.setCreateUserId(authenticateUser.getId());
            entity.setState(Round.State.CREATED);
            baseMapper.insert(entity);
        } else {
            entity.setStartTime(null);
            entity.setCreateUserId(null);
            entity.setNum(null);
            updateById(entity);
        }
        return entity;
    }

}
